import random
import sys
import os.path

sys.path.insert(0, os.path.abspath('..'))

from shared import grid

# How spacious will the maze be?
# Higher value = more spacious
# Don't set too high or maze will take a long time to generate.
POROSITY = 1.4


def createMaze(x_size, y_size):
    ####Sets up gameboard#######################
    maze = []
    for y in range(0, y_size):

        maze.append([0])
        for x in range(0, x_size - 1):
            if y == 0 or y == y_size - 1 or x == x_size - 2:
                maze[y].append(0)
            else:
                maze[y].append(2)

    ############################################
    ########Selects The Solution Gates##########
    max_random_moves = x_size * y_size / (x_size + y_size)
    if max_random_moves == 1:
        return "No Solution Error, Maze Cannot be random"
    else:
        blockAsolution = []
        blockBsolution = []

        Ay = random.choice('ts')
        if Ay == "s":
            Ay = random.randint(1, y_size - 1)
        else:
            Ay = 0

        if Ay == 0:
            Ax = random.randint(1, x_size - 1)
            maze[0][Ax] = 1
        else:
            Ax = 0
            maze[Ay][0] = 1

        By = random.choice('ts')
        if By == "s":
            By = random.randint(1, y_size - 1)
        else:
            By = y_size - 1

        if By == y_size - 1:
            Bx = random.randint(1, x_size - 1)
            maze[y_size - 1][Bx] = 1
        else:
            Bx = x_size - 1
            maze[By][x_size - 1] = 1

    return maze

    #############################################
    ##############Drawing Initial################
    rtmoves = 0
    while rtmoves < max_random_moves:
        rtmoves += 1


def whatArePossibleMoves(current_x, current_y):
    print("NO CODE")


def make_maze_from_edges(passable, edges_h, edges_v):
    maze = grid.MazeGrid(len(edges_v[0]) + len(passable[0]),
                             len(edges_h) + len(passable))

    for x in range(maze.sizeX):
        for y in range(maze.sizeY):
            if x % 2 == 1:
                if y % 2 == 1:
                    maze[x, y] = bool(passable[y // 2][x // 2])
                else:
                    maze[x, y] = edges_h[y // 2][x // 2]
            else:
                if y % 2 == 1:
                    maze[x, y] = edges_v[y // 2][x // 2]
                else:
                    try:
                        maze[x, y] = (
                           edges_v[y // 2][x // 2] &
                           edges_h[y // 2][x // 2] &
                           edges_v[y // 2 - 1][x // 2] &
                           edges_h[y // 2][x // 2 - 1]
                           )
                    except IndexError:
                        pass

    make_entrance(maze)
    make_exit(maze)
    return maze


def make_exit(maze):
    """Generate exit at last available square."""
    for x in range(maze.sizeX - 1, -1, -1):
        for y in range(maze.sizeY - 1, -1, -1):
            if maze[x, y]:
                maze.add_exit(x, y)
                return


def make_entrance(maze):
    """Generate entrance at first available square."""
    for x in range(maze.sizeX):
        for y in range(maze.sizeY):
            if maze[x, y]:
                maze.set_entrance(x, y)
                return


def DepthFirstGenerator(width, height):
    passable = [
        [0 for _ in range(width)]
        for _ in range(height)
        ]

    edges_h = [
        [False for _ in range(width)]
        for _ in range(height + 1)
        ]

    edges_v = [
        [False for _ in range(width + 1)]
        for _ in range(height)
        ]

    passable[0][0] = 1

    record = [
        (0, 0)
    ]

    while len(record) != 0:
        last = record[-1]

        north = last[0], last[1] - 1, 'N'
        west = last[0] - 1, last[1], 'W'
        east = last[0] + 1, last[1], 'E'
        south = last[0], last[1] + 1, 'S'

        directions = [north, west, east, south]
        possible = []

        for di in directions:

            if di[0] < 0 or di[1] < 0 or di[0] >= width or di[1] >= height:
                continue

            # print(di)
            if passable[di[1]][di[0]] >= POROSITY:
                # print('already been here')
                continue

            possible.append(di)

        if len(possible) == 0:
            # backtrack
            record.pop()
            continue

        else:
            di = random.choice(possible)
            passable[di[1]][di[0]] += random.uniform(0, 2)
            if di[2] == 'N':
                edges_h[last[1]][last[0]] = True
            elif di[2] == 'S':
                edges_h[last[1] + 1][last[0]] = True
            elif di[2] == 'W':
                edges_v[last[1]][last[0]] = True
            elif di[2] == 'E':
                edges_v[last[1]][last[0] + 1] = True
            else:
                assert False

            record.append((di[0], di[1]))

    return make_maze_from_edges(passable, edges_h, edges_v)


# print(DepthFirstGenerator(10, 10))
##
##while True:
##
##    ma = createMaze(20,15)
##
##    print (ma)
##    print ("/n")
##    time.sleep (10)
##
##
##
